<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted, reactive } from 'vue';
import {
  CubeModelConfig,
  LocateSetData,
  PlaneModelConfig
} from "@/utils/appCommon/appCommonOptions/aeLocateConfigModel";
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
import { computeScaleRate } from "@/views/apply/locateAnalysis/component/utils/commonThree";

interface Props {
  locateSetting: LocateSetData | null;
  renderParams: {
    width: number;
    height: number;
    viewMode?: number;
  };
  searchParams: Record<string, any>;
}

const props = defineProps<Props>();

// Three.js核心对象
let scene: THREE.Scene | null = null;
let camera: THREE.PerspectiveCamera | null = null;
let renderer: THREE.WebGLRenderer | null = null;
let controls: OrbitControls | null = null;
let raycaster: THREE.Raycaster | null = null;
let mouse: THREE.Vector2 | null = null;

// 网格和坐标轴相关
let gridMesh: THREE.GridHelper | null = null;
let axisLineMeshes: THREE.Object3D[] = [];
let axisTextMeshes: THREE.Object3D[] = [];
let axisLabelFont: any = null;

// 状态管理
const threeBoxRef = ref();
const threeData = reactive({
  width: 600,
  height: 600,
  bgColor: '#f0f4f8',
  compareSize: 200, // 用于计算缩放比例
  scaleRate: 1 // 物理尺寸到3D尺寸的转换比例
});

const mousePosition = reactive({
  x: 0,
  y: 0,
  z: 0
});

// 传感器数据结构
const sensors = ref<Array<{
  id: number|string;
  x: number;
  y: number;
  z: number;
  cube: THREE.Mesh;
  dynamicStyle: {
    left: string;
    top: string;
    display: string;
  };
}>>([]);

// 传感器编号计数器
let sensorCounter = 0;

// 初始化Three.js场景
// 优化：添加错误处理
function initThree() {
  try {
    if (!threeBoxRef.value || !props.locateSetting) return;

    // 清理之前的场景
    cleanup();

    // 创建新的场景
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera();
    renderer = new THREE.WebGLRenderer({ antialias: true });

    // 更新threeData的尺寸
    threeData.width = props.renderParams.width || 600;
    threeData.height = props.renderParams.height || 600;

    // 设置渲染器
    renderer.setSize(threeData.width, threeData.height);
    renderer.setPixelRatio(window.devicePixelRatio);
    threeBoxRef.value.innerHTML = '';
    threeBoxRef.value.appendChild(renderer.domElement);

    // 设置背景色
    scene.background = new THREE.Color(threeData.bgColor);

    // 设置相机
    camera.position.set(0, 0, 270);
    camera.lookAt(scene.position);
    camera.aspect = threeData.width / threeData.height;
    camera.updateProjectionMatrix();

    // 创建轨道控制器
    controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    controls.addEventListener('change', () => {
      updateAllTextPosition();
      render();
    });

    // 添加光源
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, threeData.width, threeData.height);
    scene.add(light);

    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambientLight);

    // 创建辅助工具
    raycaster = new THREE.Raycaster();
    mouse = new THREE.Vector2();

    // 添加鼠标移动监听
    window.addEventListener('mousemove', listenMouseMove);

    // 创建网格和坐标轴
    createAxis();

    // 添加传感器
    addExampleSensors();
    //createSensorBoxes();

    render();
  } catch (error) {
    console.error('初始化Three.js场景失败:', error);
  }
}

// 优化：添加防抖处理
let resizeTimeout: NodeJS.Timeout | null = null;
function resizeRenderer() {
  if (!renderer || !camera) return;

  // 防抖处理，避免频繁调整大小
  if (resizeTimeout) {
    clearTimeout(resizeTimeout);
  }

  resizeTimeout = setTimeout(() => {
    threeData.width = props.renderParams.width || 600;
    threeData.height = props.renderParams.height || 600;

    renderer!.setSize(threeData.width, threeData.height);
    camera!.aspect = threeData.width / threeData.height;
    camera!.updateProjectionMatrix();

    if (controls) {
      controls.update();
    }

    render();
    updateAllTextPosition();
  }, 100);
}

// 优化：改进字体加载错误处理
function createAxis() {
  if (!scene) return;

  // 清除现有的坐标轴
  if (axisLineMeshes.length > 0) {
    axisLineMeshes.forEach(item => {
      item.removeFromParent();
    });
    axisLineMeshes = [];
  }

  if (axisTextMeshes.length > 0) {
    axisTextMeshes.forEach(item => {
      item.removeFromParent();
    });
    axisTextMeshes = [];
  }

  // 加载字体
  const fontLoader = new FontLoader();
  fontLoader.load('/public/threefont.json',
    function(font) {
      axisLabelFont = font;
      createAxisHelper(font);
    }
  );
}

function getPlaneDimensions(){
  const modelConfig = props.locateSetting?.config?.modelConfig as PlaneModelConfig;
  const xRange = modelConfig?.xRange || 1000;
  const yRange = modelConfig?.yRange || 1000;

  // 计算缩放率，使用最大尺寸作为基准
  const maxDimension = Math.max(xRange, yRange);
  const scaleRate = computeScaleRate(maxDimension, 200); // 200作为比较尺寸
  threeData.scaleRate = scaleRate;

  // 转换为3D视图中的尺寸
  return {
    physicalXRange: xRange,
    physicalYRange: yRange,
    xRange: Math.max(xRange / scaleRate, 1),
    yRange: Math.max(yRange / scaleRate, 1),
    scaleRate
  };
}

function createAxisHelper(font: any) {
  if (!scene) return;

  // 清除现有的坐标轴
  if (axisLineMeshes.length > 0) {
    axisLineMeshes.forEach(item => {
      item.removeFromParent();
    });
    axisLineMeshes = [];
  }

  if (axisTextMeshes.length > 0) {
    axisTextMeshes.forEach(item => {
      item.removeFromParent();
    });
    axisTextMeshes = [];
  }

  // 获取缩放后的尺寸
  const { xRange, yRange } = getPlaneDimensions();
  const xhalf = xRange / 2;
  const yhalf = yRange / 2;

  // 创建材质
  const materialX = new THREE.LineBasicMaterial({ color: 0xff0000 }); // 红色X轴
  const materialY = new THREE.LineBasicMaterial({ color: 0x00ff00 }); // 绿色Y轴
  const materialGridLine = new THREE.LineBasicMaterial({ color: 0xffffff });

  // 计算轴范围和步长
  const xstep = xRange / 10;
  const ystep = yRange / 10;

  // X轴刻度和标签
  for (let i = -xhalf; i <= xhalf; i += xstep) {
    // 创建网格线
    const geometry = new THREE.BufferGeometry();
    const positions = new Float32Array([0, 0, 0, 0, yRange, 0]);
    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    const line = new THREE.Line(geometry, materialGridLine);
    axisLineMeshes.push(line);
    line.position.set(i, -yhalf, 0);
    scene.add(line);

    // 添加刻度标签（偶数位）- 参考d3-bak.vue的实现
    if (Math.abs(i + xhalf) % (2 * xstep) === 0) {
      const physicalValue = Math.round((i + xhalf) * threeData.scaleRate);
      const textLabel = physicalValue.toString();
      const textGeometry = new TextGeometry(textLabel, {
        font: font,
        size: xstep / 5,
        height: 0.1
      });
      const textMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
      const textMesh = new THREE.Mesh(textGeometry, textMaterial);
      textMesh.position.set(i - (xstep / 4), (-ystep / 2) - yhalf, 0.2);
      axisTextMeshes.push(textMesh);
      scene.add(textMesh);
    }
  }

  // Y轴刻度和标签
  for (let i = -yhalf; i <= yhalf; i += ystep) {
    // 创建网格线
    const geometry = new THREE.BufferGeometry();
    const positions = new Float32Array([0, 0, 0, xRange, 0, 0]);
    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    const line = new THREE.Line(geometry, materialGridLine);
    axisLineMeshes.push(line);
    line.position.set(-xhalf, i, 0);
    scene.add(line);

    // 添加刻度标签（偶数位）- 参考d3-bak.vue的实现
    if (Math.abs(i + yhalf) % (2 * ystep) === 0) {
      const physicalValue = Math.round((i + yhalf) * threeData.scaleRate);
      const textLabel = physicalValue.toString();
      const textGeometry = new TextGeometry(textLabel, {
        font: font,
        size: ystep / 5,
        height: 0.1
      });
      const textMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
      const textMesh = new THREE.Mesh(textGeometry, textMaterial);
      textMesh.position.set(-xstep - xhalf, i, 0.2);
      axisTextMeshes.push(textMesh);
      scene.add(textMesh);
    }
  }

  // XYZ轴线
  // X轴
  const xAxisGeometry = new THREE.BufferGeometry();
  const xAxisPositions = new Float32Array([0, 0, 0, xRange, 0, 0]);
  xAxisGeometry.setAttribute('position', new THREE.BufferAttribute(xAxisPositions, 3));
  const xAxisLine = new THREE.Line(xAxisGeometry, materialX);
  xAxisLine.position.set(-xhalf, -yhalf, 0);
  axisLineMeshes.push(xAxisLine);
  scene.add(xAxisLine);

  // Y轴
  const yAxisGeometry = new THREE.BufferGeometry();
  const yAxisPositions = new Float32Array([0, 0, 0, 0, yRange, 0]);
  yAxisGeometry.setAttribute('position', new THREE.BufferAttribute(yAxisPositions, 3));
  const yAxisLine = new THREE.Line(yAxisGeometry, materialY);
  yAxisLine.position.set(-xhalf, -yhalf, 0);
  axisLineMeshes.push(yAxisLine);
  scene.add(yAxisLine);

  render();
}

// 优化：改进传感器标签显示逻辑
function judgeSensorTextShow(cube: THREE.Mesh): boolean {
  if (!camera || !scene) return false;

  // 检查传感器是否在相机视野内
  const frustum = new THREE.Frustum();
  const cameraMatrix = new THREE.Matrix4().multiplyMatrices(
    camera.projectionMatrix,
    camera.matrixWorldInverse
  );
  frustum.setFromProjectionMatrix(cameraMatrix);

  return frustum.intersectsObject(cube);
}

// 优化：改进清理函数
function cleanup() {
  // 清除防抖定时器
  if (resizeTimeout) {
    clearTimeout(resizeTimeout);
    resizeTimeout = null;
  }

  if (renderer) {
    renderer.dispose();
    renderer = null;
  }
  if (scene) {
    scene.clear();
    scene = null;
  }
  if (controls) {
    controls.dispose();
    controls = null;
  }

  window.removeEventListener('mousemove', listenMouseMove);
  axisLineMeshes = [];
  axisTextMeshes = [];
  sensors.value = [];
  sensorCounter = 0;
  camera = null;
  raycaster = null;
  mouse = null;
  gridMesh = null;
  axisLabelFont = null;
}

// 创建传感器
function createSensorBoxes() {
  if (!scene || !props.locateSetting) return;

  // 清除旧的传感器
  sensors.value.forEach(item => {
    if (item.cube) {
      scene?.remove(item.cube);
    }
  });
  sensors.value = [];
  sensorCounter = 0;

  const sensorSettings = props.locateSetting.sensorSettings || [];

  // 从配置中创建传感器
  sensorSettings.forEach((sensorSetting: any, index: number) => {
    const x = sensorSetting.x || 0;
    const y = sensorSetting.y || 0;
    const z = sensorSetting.z || 0;

    const numer = index + 1;
    const id = sensorSetting.id || numer;

    // 计算3D坐标
    const cubexyz = transferPlaneDataTo3dData(x, y, z);

    // 创建立方体，使用缩放后的尺寸
    const cube = createCubeItem(Math.max(2, 5 / threeData.scaleRate));
    cube.position.set(cubexyz.x, cubexyz.y, cubexyz.z);
    scene?.add(cube);

    // 判断是否可见
    const isVisible = judgeSensorTextShow(cube);

    // 添加到传感器列表
    sensors.value.push({
      id,
      x,
      y,
      z,
      cube,
      dynamicStyle: {
        left: '0px',
        top: '0px',
        display: isVisible ? 'block' : 'none'
      }
    });
  });

  // 更新所有标签位置
  updateAllTextPosition();
  render();
}

// 平面坐标转换为3D坐标
function transferPlaneDataTo3dData(x: number, y: number,z:number): { x: number; y: number; z: number } {
  const { physicalXRange, physicalYRange, scaleRate } = getPlaneDimensions();
  // 计算缩放后的坐标，并调整到立方体中心
  const scaledX = (x / scaleRate) - (physicalXRange / 2 / scaleRate);
  const scaledY = (y / scaleRate) - (physicalYRange / 2 / scaleRate);
  return { x: scaledX, y: scaledY, z: 0 };
}

// 创建传感器立方体
function createCubeItem(size: number): THREE.Mesh {
  const cubeGeometry = new THREE.BoxGeometry(size, size, size);
  const material = new THREE.MeshBasicMaterial({
    color: 0x0000ee
  });
  const cube = new THREE.Mesh(cubeGeometry, material);
  return cube;
}

// 添加传感器
function addSensor(x: number, y: number, z: number, existingId?: number|string): number|string {
  if (!scene) return -1;

  const currentId = existingId || `sensor_${++sensorCounter}`;

  // 计算3D坐标
  const cubexyz = transferPlaneDataTo3dData(x, y, 0);

  // 创建传感器立方体，使用缩放后的尺寸
  const cube = createCubeItem(4);
  cube.position.set(cubexyz.x, cubexyz.y, cubexyz.z);
  scene.add(cube);

  // 判断是否可见
  const isVisible = judgeSensorTextShow(cube);

  // 添加传感器数据
  sensors.value.push({
    id: currentId,
    x,
    y,
    z,
    cube,
    dynamicStyle: {
      left: '0px',
      top: '0px',
      display: isVisible ? 'block' : 'none'
    }
  });

  // 更新标签位置
  updateTextPosition(sensors.value.length - 1, cube);

  render();
  return currentId;
}

// 删除传感器
function removeSensor(id: number|string): boolean {
  if (!scene) return false;

  const index = sensors.value.findIndex(sensor => sensor.id === id);
  if (index === -1) return false;

  // 移除3D对象
  scene.remove(sensors.value[index].cube);

  // 从数组中删除
  sensors.value.splice(index, 1);

  render();
  return true;
}

// 添加示例传感器 - 参考立方体组件的实现
function addExampleSensors() {
  if (!scene || !props.locateSetting) return;

  const modelConfig = props.locateSetting.config?.modelConfig as PlaneModelConfig;
  const { physicalXRange, physicalYRange } = getPlaneDimensions();

  // 添加一些示例传感器
  addSensor(physicalXRange * 0.2, physicalYRange * 0.2, 0);
  addSensor(physicalXRange * 0.8, physicalYRange * 0.3, 0);
  addSensor(physicalXRange * 0.5, physicalYRange * 0.7, 0);
  addSensor(physicalXRange * 0.3, physicalYRange * 0.9, 0);

  render();
}

// 更新所有传感器标签位置
function updateAllTextPosition() {
  sensors.value.forEach((item, index) => {
    if (item.cube) {
      updateTextPosition(index, item.cube);
    }
  });
}

// 更新单个传感器标签位置
function updateTextPosition(index: number, cube: THREE.Mesh) {
  if (!camera) return;

  const vector = new THREE.Vector3();
  cube.getWorldPosition(vector);
  vector.project(camera);

  const x = (vector.x * 0.5 + 0.5) * threeData.width;
  const y = (-vector.y * 0.5 + 0.5) * threeData.height;

  if (sensors.value[index]) {
    sensors.value[index].dynamicStyle.left = `${x + 10}px`;
    sensors.value[index].dynamicStyle.top = `${y - 10}px`;
  }
}

// 监听鼠标移动
function listenMouseMove(event: MouseEvent) {
  if (!renderer || !camera || !raycaster || !mouse) return;

  const rect = renderer.domElement.getBoundingClientRect();
  const x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
  const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

  mouse.set(x, y);
  raycaster.setFromCamera(mouse, camera);

  // 找出所有可交互的物体
  const intersectables: THREE.Object3D[] = [];
  if (gridMesh) {
    intersectables.push(gridMesh);
  }
  sensors.value.forEach(sensor => {
    intersectables.push(sensor.cube);
  });

  // 检查射线相交
  const intersects = raycaster.intersectObjects(intersectables, false);
  if (intersects.length > 0) {
    const intersection = intersects[0];
    const position = intersection.point;

    // 更新鼠标位置（转换为物理尺寸）
    const { physicalXRange, physicalYRange, scaleRate } = getPlaneDimensions();
    mousePosition.x = Number((position.x * scaleRate + physicalXRange / 2).toFixed(1));
    mousePosition.y = Number((position.y * scaleRate + physicalYRange / 2).toFixed(1));
    mousePosition.z = Number((position.z * scaleRate).toFixed(1));
  }
}

// 渲染
function render() {
  if (renderer && scene && camera) {
    renderer.render(scene, camera);
  }
}

// 监听locateSetting参数变化
watch(
  () => props.locateSetting,
  (newVal) => {
    if (newVal) {
      console.log('平面定位配置参数变化:', newVal);
      initThree();
    }
  },
  { deep: true, immediate: true }
);

// 监听renderParams参数变化
watch(
  () => props.renderParams,
  (newVal) => {
    console.log('渲染参数变化:', newVal);
    resizeRenderer();
  },
  { deep: true }
);

// 监听searchParams参数变化
watch(
  () => props.searchParams,
  (newVal) => {
    console.log('搜索参数变化:', newVal);
    // 平面视图对searchParams变化的处理逻辑
  },
  { deep: true }
);

// 组件挂载
onMounted(() => {
  console.log('平面定位组件已挂载');
  initThree();
});

// 组件卸载
onUnmounted(() => {
  console.log('平面定位组件已卸载');
  cleanup();
});

// 暴露方法给父组件
defineExpose({
  addSensor,
  removeSensor,
  mousePosition
});
</script>

<template>
  <div
    class="plane-locate-container"
    :style="{
      width: `${renderParams.width}px`,
      height: `${renderParams.height}px`
    }"
  >
    <div class="title">
      鼠标: X={{ mousePosition.x.toFixed(1) }}mm, Y={{ mousePosition.y.toFixed(1) }}mm, Z={{ mousePosition.z.toFixed(1) }}mm
    </div>
    <div ref="threeBoxRef" class="three-container">
    </div>
    <!-- 传感器编号显示 -->
    <template v-for="(sensor, index) in sensors" :key="index">
      <div class="sensor-label" :style="sensor.dynamicStyle">
        {{ sensor.id }}
      </div>
    </template>
  </div>
</template>

<style scoped lang="scss">
.plane-locate-container {
  position: relative;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
}

.title {
  position: relative;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  text-align: center;
  font-size: 11px;
  background-color: transparent;
}

.three-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.sensor-label {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  display: inline-block;
  line-height: 1;
  color: orangered;
  font-size: 13px;
  pointer-events: none; /* 避免影响鼠标交互 */
}

:deep(canvas) {
  display: block;
  width: 100% !important;
  height: 100% !important;
}
</style>

